package com.amikomgamedev.labirinhantu.entity;

import java.util.ArrayList;

import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.entity.modifier.MoveModifier;
import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.entity.sprite.TiledSprite;
import org.andengine.ui.activity.SimpleBaseGameActivity;

import com.amikomgamedev.labirinhantu.Cheat;
import com.amikomgamedev.labirinhantu.Server_Data;
import com.amikomgamedev.labirinhantu.Utils;
import com.amikomgamedev.labirinhantu.game.Game_Config;
import com.amikomgamedev.labirinhantu.game.Game_Data;
import com.amikomgamedev.labirinhantu.grafik.Grafik_Anim;
import com.amikomgamedev.labirinhantu.grafik.Grafik_Define;

public class Entity_Mc	implements	Grafik_Define
									, Game_Data
									, Grafik_Anim
									, Cheat
{
	public final int	MOVE_RIGHT		= 0;
	public final int	MOVE_DOWN		= 1;
	public final int	MOVE_LEFT		= 2;
	public final int	MOVE_UP			= 3;
	public final int	IDLE			= 4;
	public final int	DIE_SINK		= 5;
	public final int	DIE_ON_FIRE		= 6;
	public final int	DIE_SEE_GHOST	= 7;
	public final int	WIN				= 8;
	private int			state_Cur		= -1;

	private int	move_Back_Count		= 0;
	private int	move_Right_Count	= 0;
	private int	move_Left_Count		= 0;	
	private int direction_Mc		= -1;
	
	private final int[][]	DIR_MC	=
	    {
		{
		    MOVE_RIGHT, MOVE_RIGHT, MOVE_RIGHT, MOVE_RIGHT, // easy 1 - 4
		    MOVE_RIGHT, MOVE_RIGHT, MOVE_RIGHT, MOVE_RIGHT, // easy 5 - 8
		    MOVE_RIGHT, MOVE_RIGHT, MOVE_RIGHT, MOVE_RIGHT, MOVE_RIGHT, MOVE_DOWN, // medium
		    MOVE_RIGHT, MOVE_LEFT, MOVE_DOWN, MOVE_RIGHT, MOVE_RIGHT, MOVE_DOWN // hard
		},
		{
		    MOVE_RIGHT, MOVE_RIGHT, MOVE_LEFT, MOVE_RIGHT, 
		    MOVE_LEFT, MOVE_DOWN, MOVE_DOWN, MOVE_RIGHT, 
		    MOVE_LEFT, MOVE_RIGHT, MOVE_RIGHT, MOVE_DOWN, MOVE_RIGHT, MOVE_LEFT, 
		    MOVE_DOWN, MOVE_RIGHT, MOVE_RIGHT, MOVE_DOWN, MOVE_LEFT, MOVE_UP,
		},
		{
		    MOVE_RIGHT, MOVE_DOWN, MOVE_RIGHT, MOVE_RIGHT, 
		    MOVE_DOWN, MOVE_RIGHT, MOVE_RIGHT, 
		    MOVE_RIGHT, MOVE_LEFT, MOVE_RIGHT, 
		    
		},
	    };
	
	private	float	p_X;
	private	float	p_Y;
	private	float	p_Width;
	private	float	p_Height;
	private float	p_Bagi	= 1f;
	
	private float	block_Size	= 20;

	private float	start_X;
	private float	start_Y;
	
	private boolean isMoving		= false;
	
	private Scene					m_Scene;
	private AnimatedSprite			m_Mc, m_Renang;
	private Rectangle[]				m_Mc_Rec = new Rectangle[4];
	private	ArrayList<Rectangle>	m_Wall;
	private TiledSprite 			m_Navigasi;
	
	public Entity_Mc(SimpleBaseGameActivity p_Activity
			, Scene p_Scene
			, AnimatedSprite[] p_Mc
			, ArrayList<Rectangle> p_Wall
			, TiledSprite p_Navigasi)
	{
		m_Scene	= p_Scene;
		m_Mc	= p_Mc[0];
		m_Renang	= p_Mc[1];
		m_Wall	= p_Wall;
		m_Navigasi	= p_Navigasi;
		
		for (int i = 0; i < m_Mc_Rec.length; i++)
		{
			switch (i)
			{
				case MOVE_RIGHT:
					p_X		= m_Mc.getWidth();
					p_Y 		= 0;
					p_Width		= m_Mc.getWidth() / p_Bagi * 2;
					p_Height	= m_Mc.getHeight();
					break;
				case MOVE_DOWN:
					p_X			= 0;
					p_Y 		= m_Mc.getHeight();
					p_Width		= m_Mc.getWidth();
					p_Height	= m_Mc.getHeight() / p_Bagi;			
					break;
				case MOVE_LEFT:
					p_X			= - m_Mc.getWidth() / p_Bagi * 2;
					p_Y 		= 0;
					p_Width		= m_Mc.getWidth() / p_Bagi * 2;
					p_Height	= m_Mc.getHeight();
					break;
				case MOVE_UP:
					p_X			= 0;
					p_Y 		= - m_Mc.getHeight() / p_Bagi;
					p_Width		= m_Mc.getWidth();
					p_Height	= m_Mc.getHeight() / p_Bagi;
					break;
			}
			
			if (m_Mc_Rec[i] == null)
				m_Mc_Rec[i] = new Rectangle(p_X, p_Y
						, p_Width , p_Height
						, p_Activity.getVertexBufferObjectManager());
			
			if (!Game_Config.DEBUG)
				m_Mc_Rec[i].setVisible(false);
			
			m_Mc.attachChild(m_Mc_Rec[i]);
		}

		start_X			= m_Mc.getX();
		start_Y			= m_Mc.getY();
		
		checkFirstStart();
	}
	
	public void onUpdate(float p_Sec)
	{	    
		switch (state_Cur)
		{
			case MOVE_RIGHT:
				
				if (isMoving) return;
				
				for (int i = 0; i < m_Wall.size(); i++)
					if (m_Mc_Rec[state_Cur].collidesWith(m_Wall.get(i)))
						return;
				
				m_Mc.animate(GAME_PLAY_MC_DUR[state_Cur]
						, GAME_PLAY_MC_FRAME[state_Cur][0]
						, GAME_PLAY_MC_FRAME[state_Cur][1]
						, true);
				
				m_Renang.animate(GAME_PLAY_MC_SWIM_DUR[state_Cur]
						, GAME_PLAY_MC_SWIM_FRAME[state_Cur][0]
						, GAME_PLAY_MC_SWIM_FRAME[state_Cur][1]
						, true);
				
				m_Mc.registerEntityModifier(
						new MoveModifier(FAST_SPEED ? SPEED : TIME_PER_BLOCK, m_Mc.getX()
								, m_Mc.getX() + block_Size * 4
								, m_Mc.getY()
								, m_Mc.getY()));
				
				m_Renang.registerEntityModifier(
						new MoveModifier(FAST_SPEED ? SPEED : TIME_PER_BLOCK, m_Mc.getX() - 15
								, m_Mc.getX() + block_Size * 4 - 15
								, m_Mc.getY()
								, m_Mc.getY()));
				
				m_Scene.registerUpdateHandler(new TimerHandler(FAST_SPEED ? SPEED : TIME_PER_BLOCK, new ITimerCallback()
				{
					public void onTimePassed(TimerHandler pTimerHandler)
					{
						isMoving	= false;
						m_Mc.stopAnimation();
					}
				}));

				if (direction_Mc == MOVE_LEFT)
				{
				    Server_Data.setBack(Server_Data.getBack()-1);
					
//					m_Navigasi.registerEntityModifier(new RotationByModifier(TIME_PER_BLOCK, 90));
					move_Back_Count++;
				}
				else if (direction_Mc == MOVE_DOWN)
				{
				    Server_Data.setLeft(Server_Data.getLeft()-1);
//					m_Navigasi.registerEntityModifier(new RotationByModifier(TIME_PER_BLOCK, 90));
					move_Left_Count++;
				}
				else if (direction_Mc == MOVE_UP)
				{
				    Server_Data.setRight(Server_Data.getRight()-1);
//					m_Navigasi.registerEntityModifier(new RotationByModifier(TIME_PER_BLOCK, 90));
					move_Right_Count++;
				}

//				Utils.TRACE("move_Forward_Count\t= " +move_Forward_Count);
				Utils.TRACE("move_Back_Count\t= " +move_Back_Count);
				Utils.TRACE("move_Right_Count\t= " +move_Right_Count);
				Utils.TRACE("move_Left_Count\t= " +move_Left_Count);
				
				direction_Mc 	= MOVE_RIGHT;
				isMoving		= true;
				
				m_Navigasi.setCurrentTileIndex(1);
				
				break;
				
			case MOVE_DOWN:
				
				if (isMoving) return;
				
				for (int i = 0; i < m_Wall.size(); i++)
					if (m_Mc_Rec[state_Cur].collidesWith(m_Wall.get(i)))
						return;

				m_Mc.animate(GAME_PLAY_MC_DUR[state_Cur]
						, GAME_PLAY_MC_FRAME[state_Cur][0]
						, GAME_PLAY_MC_FRAME[state_Cur][1]
						, true);
				
				m_Renang.animate(GAME_PLAY_MC_SWIM_DUR[state_Cur]
						, GAME_PLAY_MC_SWIM_FRAME[state_Cur][0]
						, GAME_PLAY_MC_SWIM_FRAME[state_Cur][1]
						, true);
				
				m_Mc.registerEntityModifier(
						new MoveModifier(FAST_SPEED ? SPEED : TIME_PER_BLOCK, m_Mc.getX()
								, m_Mc.getX()
								, m_Mc.getY()
								, m_Mc.getY() +  block_Size * 4));
				
				m_Renang.registerEntityModifier(
						new MoveModifier(FAST_SPEED ? SPEED : TIME_PER_BLOCK, m_Mc.getX() - 15
								, m_Mc.getX() - 15
								, m_Mc.getY()
								, m_Mc.getY() +  block_Size * 4));
				
				m_Scene.registerUpdateHandler(new TimerHandler(FAST_SPEED ? SPEED : TIME_PER_BLOCK, new ITimerCallback()
				{
					public void onTimePassed(TimerHandler pTimerHandler)
					{
						isMoving	= false;
						m_Mc.stopAnimation();
					}
				}));

				if (direction_Mc == MOVE_UP)
				{
				    Server_Data.setBack(Server_Data.getBack()-1);
					move_Back_Count++;
				}
				else if (direction_Mc == MOVE_LEFT)
				{
				    Server_Data.setLeft(Server_Data.getLeft()-1);
					move_Left_Count++;
				}
				else if (direction_Mc == MOVE_RIGHT)
				{
				    Server_Data.setRight(Server_Data.getRight()-1);
					move_Right_Count++;
				}
//				Utils.TRACE("move_Forward_Count\t= " +move_Forward_Count);
				Utils.TRACE("move_Back_Count\t= " +move_Back_Count);
				Utils.TRACE("move_Right_Count\t= " +move_Right_Count);
				Utils.TRACE("move_Left_Count\t= " +move_Left_Count);

				direction_Mc	= MOVE_DOWN;
				isMoving		= true;

				m_Navigasi.setCurrentTileIndex(2);
				
				break;
				
			case MOVE_LEFT:
				
				if (isMoving) return;
				
				for (int i = 0; i < m_Wall.size(); i++)
					if (m_Mc_Rec[state_Cur].collidesWith(m_Wall.get(i)))
						return;

				m_Mc.animate(GAME_PLAY_MC_DUR[state_Cur]
						, GAME_PLAY_MC_FRAME[state_Cur][0]
						, GAME_PLAY_MC_FRAME[state_Cur][1]
						, true);
				
				m_Renang.animate(GAME_PLAY_MC_SWIM_DUR[state_Cur]
						, GAME_PLAY_MC_SWIM_FRAME[state_Cur][0]
						, GAME_PLAY_MC_SWIM_FRAME[state_Cur][1]
						, true);
				
				m_Mc.registerEntityModifier(
						new MoveModifier(FAST_SPEED ? SPEED : TIME_PER_BLOCK, m_Mc.getX()
								, m_Mc.getX() - block_Size * 4
								, m_Mc.getY()
								, m_Mc.getY()));
				
				m_Renang.registerEntityModifier(
						new MoveModifier(FAST_SPEED ? SPEED : TIME_PER_BLOCK, m_Mc.getX() - 15
								, m_Mc.getX() - block_Size * 4 - 15
								, m_Mc.getY()
								, m_Mc.getY()));
				
				m_Scene.registerUpdateHandler(new TimerHandler(FAST_SPEED ? SPEED : TIME_PER_BLOCK, new ITimerCallback()
				{
					public void onTimePassed(TimerHandler pTimerHandler)
					{
						isMoving	= false;
						m_Mc.stopAnimation();
					}
				}));

				if (direction_Mc == MOVE_RIGHT)
				{
				    Server_Data.setBack(Server_Data.getBack()-1);
					move_Back_Count++;
				}
				else if (direction_Mc == MOVE_UP)
				{
				    Server_Data.setLeft(Server_Data.getLeft()-1);
					move_Left_Count++;
				}
				else if (direction_Mc == MOVE_DOWN)
				{
				    Server_Data.setRight(Server_Data.getRight()-1);
					move_Right_Count++;
				}
				
//				Utils.TRACE("move_Forward_Count\t= " +move_Forward_Count);
				Utils.TRACE("move_Back_Count\t= " +move_Back_Count);
				Utils.TRACE("move_Right_Count\t= " +move_Right_Count);
				Utils.TRACE("move_Left_Count\t= " +move_Left_Count);
				Utils.TRACE("move_Left_Count server\t= " +Server_Data.getLeft());
				
				direction_Mc	= MOVE_LEFT;
				isMoving		= true;

				m_Navigasi.setCurrentTileIndex(3);
				
				break;
				
			case MOVE_UP:
				
				if (isMoving) return;
				
				for (int i = 0; i < m_Wall.size(); i++)
					if (m_Mc_Rec[state_Cur].collidesWith(m_Wall.get(i)))
						return;

				m_Mc.animate(GAME_PLAY_MC_DUR[state_Cur]
						, GAME_PLAY_MC_FRAME[state_Cur][0]
						, GAME_PLAY_MC_FRAME[state_Cur][1]
						, true);
				
				m_Renang.animate(GAME_PLAY_MC_SWIM_DUR[state_Cur]
						, GAME_PLAY_MC_SWIM_FRAME[state_Cur][0]
						, GAME_PLAY_MC_SWIM_FRAME[state_Cur][1]
						, true);
				
				m_Mc.registerEntityModifier(
						new MoveModifier(FAST_SPEED ? SPEED : TIME_PER_BLOCK, m_Mc.getX()
								, m_Mc.getX()
								, m_Mc.getY()
								, m_Mc.getY() - block_Size * 4));
				
				m_Renang.registerEntityModifier(
						new MoveModifier(FAST_SPEED ? SPEED : TIME_PER_BLOCK, m_Mc.getX() - 15
								, m_Mc.getX() - 15
								, m_Mc.getY()
								, m_Mc.getY() - block_Size * 4));
				
				m_Scene.registerUpdateHandler(new TimerHandler(FAST_SPEED ? SPEED : TIME_PER_BLOCK, new ITimerCallback()
				{
					public void onTimePassed(TimerHandler pTimerHandler)
					{
						isMoving	= false;
						m_Mc.stopAnimation();
					}
				}));

				if (direction_Mc == MOVE_DOWN)
				{
				    Server_Data.setBack(Server_Data.getBack()-1);
					move_Back_Count++;
				}
				else if (direction_Mc == MOVE_RIGHT)
				{
				    Server_Data.setLeft(Server_Data.getLeft()-1);
					move_Left_Count++;
				}
				else if (direction_Mc == MOVE_LEFT)
				{
				    Server_Data.setRight(Server_Data.getRight()-1);
					move_Right_Count++;
				}
//				Utils.TRACE("move_Forward_Count\t= " +move_Forward_Count);
				Utils.TRACE("move_Back_Count\t= " +move_Back_Count);
				Utils.TRACE("move_Right_Count\t= " +move_Right_Count);
				Utils.TRACE("move_Left_Count\t= " +move_Left_Count);
				
				direction_Mc	= MOVE_UP;
				isMoving		= true;

				m_Navigasi.setCurrentTileIndex(0);
				
				break;
		}
	}
	
	public void switchState(int p_State)
	{
		state_Cur	= p_State;
		
		switch (state_Cur)
		{
			case MOVE_RIGHT:
				if (!m_Mc.isFlippedHorizontal())
				{
					m_Mc.setFlippedHorizontal(true);
					m_Renang.setFlippedHorizontal(true);
				}
				break;
			case MOVE_DOWN:
				break;
			case MOVE_LEFT:
				if (m_Mc.isFlippedHorizontal())
				{
					m_Mc.setFlippedHorizontal(false);
					m_Renang.setFlippedHorizontal(false);
				}
				break;
			case MOVE_UP:							
				break;
			case IDLE:							
				break;
			case DIE_SINK:							
				break;
			case DIE_ON_FIRE:							
				break;
			case DIE_SEE_GHOST:							
				break;
			case WIN:							
				break;
		}
	}
	
	public void respawn_Mc()
	{
		m_Mc.setPosition(start_X, start_Y);
	}
	
	private void checkFirstStart()
	{
	    direction_Mc = DIR_MC[Server_Data.getStage()][Server_Data.getMap()];
	    
	    switch (direction_Mc)
	    {
		case MOVE_RIGHT:
		    
		    m_Mc.setCurrentTileIndex(GAME_PLAY_MC_FRAME[direction_Mc][0]);			
		    m_Renang.setCurrentTileIndex(GAME_PLAY_MC_FRAME[direction_Mc][0]);
		    
		    if (!m_Mc.isFlippedHorizontal())
		    {
			m_Mc.setFlippedHorizontal(true);
			m_Renang.setFlippedHorizontal(true);
		    }
			
		    m_Navigasi.setCurrentTileIndex(1);
		    
		    break;
		    
		case MOVE_DOWN:
		    
		    m_Mc.setCurrentTileIndex(GAME_PLAY_MC_FRAME[direction_Mc][0]);			
		    m_Renang.setCurrentTileIndex(GAME_PLAY_MC_FRAME[direction_Mc][0]);
			
		    m_Navigasi.setCurrentTileIndex(2);
		    
		    break;
		    
		case MOVE_LEFT:
		    
		    m_Mc.setCurrentTileIndex(GAME_PLAY_MC_FRAME[direction_Mc][0]);			
		    m_Renang.setCurrentTileIndex(GAME_PLAY_MC_FRAME[direction_Mc][0]);
		
		    if (m_Mc.isFlippedHorizontal())
		    {
			m_Mc.setFlippedHorizontal(false);
			m_Renang.setFlippedHorizontal(false);
		    }
		    
		    m_Navigasi.setCurrentTileIndex(3);
		    
		    break;
		    
		case MOVE_UP:
		    
		    m_Mc.setCurrentTileIndex(GAME_PLAY_MC_FRAME[direction_Mc][0]);			
		    m_Renang.setCurrentTileIndex(GAME_PLAY_MC_FRAME[direction_Mc][0]);
			
		    m_Navigasi.setCurrentTileIndex(0);
		    
		    break;
	    }
	}
}
